package com.joey.cloud.annotation.auth;

import com.alibaba.fastjson.JSONObject;
import com.joey.cloud.communal.constant.BaseConstant;
import com.joey.cloud.communal.constant.CaffeineConstant;
import com.joey.cloud.communal.dto.UserAuthDto;
import com.joey.cloud.communal.utils.JwtUtils;
import com.joey.cloud.communal.utils.ResponseUtil;
import com.joey.cloud.provider.cache.CacheFeignService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Set;

/**
 * 权限注解-实现
 * @author joey
 */
@Component
@Aspect
@Slf4j
public class JoeHadAuthAspect {
    @Resource
    CacheFeignService cacheFeignService;

    @Pointcut("@annotation(com.joey.cloud.annotation.auth.JoeHadAuth)")
    public void handle() {}

    @Around("handle() && @annotation(joeHadAuth)")
    public Object action(ProceedingJoinPoint joinPoint, JoeHadAuth joeHadAuth) {
        try {
            String token = JwtUtils.getTokenByHeader();
            //校验token是否为空
            if(StringUtils.isBlank(token)){
                ResponseUtil.handle(ResponseUtil.noAuthority1());
                return null;
            }
            String jwt = token.replace(BaseConstant.TOKEN_BEARER, BaseConstant.STR_EMPTY).trim();
            //校验token是否过期
            if(JwtUtils.isExpiration(jwt)){
                ResponseUtil.handle(ResponseUtil.noAuthority2());
                return null;
            }
            String type = joeHadAuth.type();
            String values = joeHadAuth.values();
            if(StringUtils.isBlank(type)||StringUtils.isBlank(values)){
                //无权限要求则放行
                return joinPoint.proceed();
            }
            //获取权限信息 解析token
            Long currentUserId = JwtUtils.getCurrentUserIdNoException();
            if(currentUserId == null){
                ResponseUtil.handle(ResponseUtil.noAuthority3());
                return null;
            }
            UserAuthDto userAuthDto = null;
            if(cacheFeignService != null){
                ResponseUtil res = cacheFeignService.caffeineGet(CaffeineConstant.cacheAuth, BaseConstant.AUTH_PWD+currentUserId.toString());
                if(res!=null&&res.getSuccess()&&res.getData()!=null){
                    userAuthDto = JSONObject.parseObject(res.getData().toString(), UserAuthDto.class);
                }
            }
            if(userAuthDto == null){
                userAuthDto = JwtUtils.getUserInfo(jwt);
            }
            //校验token权限是否为空
            if(userAuthDto==null||userAuthDto.getGroupList()==null||userAuthDto.getRoleList()==null){
                ResponseUtil.handle(ResponseUtil.noAuthority3());
                return null;
            }
            String[] filterList = values.split(BaseConstant.SPITS_STR1);
            //校验是否是超级管理员,如果是，则放行
            if(!hadSuperAdmin(userAuthDto.getRoleList())){
                Set<String> keyList = null;
                if(BaseConstant.ROLE.equals(type)){
                    keyList = userAuthDto.getRoleList();
                }else if (BaseConstant.GROUP.equals(type)){
                    keyList = userAuthDto.getGroupList();
                }
                //否则校验token权限是否匹配
                if(checkRoles(keyList,filterList)){
                    ResponseUtil.handle(ResponseUtil.noAuthority3());
                    return null;
                }
            }
            return joinPoint.proceed();
        }catch (Throwable e){
            ResponseUtil.handle(ResponseUtil.noAuthority2());
        }
        return null;
    }

    /**
     * 是否是超级管理员
     * @param roleKeyList
     * @return
     */
    private boolean hadSuperAdmin(Set<String> roleKeyList) {
        for(String roleKey:roleKeyList){
            if(BaseConstant.SUPER_ADMIN.equals(roleKey.toUpperCase())){
                return true;
            }
        }
        return false;
    }

    /**
     * 校验是否存在权限
     * @param authKeyList 用户token权限列表
     * @param filterList 限制权限列表
     * @return
     */
    private boolean checkRoles(Set<String> authKeyList, String[] filterList) {
        for(String filter:filterList){
            for(String authKey:authKeyList){
                if(filter.toUpperCase().equals(authKey.toUpperCase())){
                    return false;
                }
            }
        }
        return true;
    }
}
